function game2048(){

    let len=4;
    let size=20;
    let margin=4;
    let score=0
    let winNum=2048
    let isGameOver=false

    let view =new View(len,size,margin)
    let board =new Board(len)

    //触控变量
    let startx,starty,endx,endy

    view.init()
    board.init()
    
    board.onGenerate=function(e){
        view.addNum(e.x,e.y,e.num)

    }

    board.onMove=function(e){
        // console.log(e);
        view.move(e.from,e.to)

        //声音
        view.sound()

        //发生合并，更新分数
        if(e.to.num>e.from.num){
            score+=e.to.num
            view.updateScore(score)
        }

        if(e.to.num>=winNum){
            isGameOver = true;
            // alert('恭喜，您获胜了！')
            view.win()
        }

    }
    board.onMoveComplete=function(e,arr){
        setTimeout(function(){
            view.updateView(arr)
        },200)
        if(e.moved){
            setTimeout(function(){
                board.generate()
            },500)
        }
        if (!board.canMove()) {
            isGameOver = true;
            // alert('游戏结束！您本次得分为：'+score)
            view.over(score)
        }
    }
    board.generate()//先定义后调用
    board.generate()

    // $('button').eq(0).click(function(){
    //     board.moveLeft()
    // })
    // $('button').eq(1).click(function(){
    //     board.moveRight()
    // })
    // $('button').eq(2).click(function(){
    //     board.moveTop()
    // })
    // $('button').eq(3).click(function(){
    //     board.moveBottom()
    // })

    document.onkeydown=function(e){
        if(isGameOver){return false}
        switch (e.which) {
            case 37: board.moveLeft();  break;
            case 38: board.moveTop();    break;
            case 39: board.moveRight(); break;
            case 40: board.moveBottom();  break;
          }
    }

    $('#game_restart').on('click',function(){
        score=0
        restart()
    })

    function restart(){
        view.updateScore(score)
        $('#game_over').addClass('game-hide')
        $('.game-num').remove()
        board.init()
        view.init()
        board.generate()
        board.generate()
        isGameOver=false
    }

    //实现触控
    document.addEventListener('touchstart',function(e){
        startx=e.touches[0].pageX
        starty=e.touches[0].pageY

    })

	document.addEventListener('touchend',function(e){
        endx=e.changedTouches[0].pageX
        endy=e.changedTouches[0].pageY

        if(isGameOver){return false}

        let tox=endx-startx
        let toy=endy-starty
        if(Math.abs(tox)-Math.abs(toy)>0){
            if(tox>0){
                board.moveRight();
            }
            else{
                board.moveLeft();
            }
        }
        else{
            if(toy>0){
                board.moveBottom()
            }
            else{
                board.moveTop(); 
            }
        }

    })

    // document.ontouchstart=function(e){
    //     startx=e.touches[0].pageX
    //     starty=e.touches[0].pageY

       
    // }

    // document.ontouchend=function(e){
    //     endx=e.changedTouches[0].pageX
    //     endy=e.changedTouches[0].pageY

    //     if(Math.abs(endx-startx)>Math.abs(endx-starty)){
    //         if((endx-startx)>0){
    //             //右移
    //             board.moveLeft();

    //         }
    //         else{
    //             左移
    //             board.moveRight();
                
    //         }
    //     }
    //     else{
    //         if((endy-starty)>0){
    //             //下移
    //             board.moveBottom()
    //         }
    //         else{
    //             //上移
    //             board.moveTop(); 
    //         }
    //     }
    // }
}

//控制游戏视图
class View{
    constructor(len,size,margin){
        this.len=len
        this.size=size
        this.margin=margin

        this.cellcon=$('#cell-con')
        this.numcon=$('#num-con')
    }

    //初始化棋盘
    init(){
        for(let x=0;x<this.len;x++){
            for(let y=0;y<this.len;y++){
                let cell=$('<div>').addClass('game-cell').css({
                    left:this.getPos(y)+'%',
                    top:this.getPos(x)+'%'
                })

                this.cellcon.append(cell)
            }
        }
    }
    getPos(n){
        return this.margin+n*(this.size+this.margin)
    }

    addNum(x,y,n){
        let num=$('<div>').addClass(`game-num game-num-${n}`).attr('id',`cell-${x}-${y}`).css({
            left:this.getPos(y)+'%',
            top:this.getPos(x)+'%'
        }).text(n)

        this.cellcon.append(num)

    }

    move(from,to){
        $(`#cell-${from.x}-${from.y}`).finish().animate({
            left:this.getPos(to.y)+'%',
            top:this.getPos(to.x)+'%'
        },150)
    }
    updateView(arr){
        $('.game-num').remove()

        for (let x = 0; x < this.len; x++) {
            for (let y = 0; y < this.len; y++) {
                if (arr[x][y]!=0) {
                    this.addNum(x,y,arr[x][y])
                    
                }
                
            }
            
        }
    }

    updateScore(score){
        $('#game_score').text(score)
      }
      win(){
        $('#game_over').removeClass('game-hide')
      $('#game_over_info p').text('恭喜，您获胜了！')
      }
      over(score){
        $('#game_over').removeClass('game-hide')
        $('#game_over_info p').text('您本次得分为：'+score)
      }
      
      sound(){
        let id=Math.floor(Math.random()*85)+1
        $('#sound').attr({
            src:`sound/na${id}.mp3`
        })
      }
}

class Board{
    constructor(len){
        this.len=len
        this.arr=[]
    }
    //定义事件
    onGenerate(){}

    onMove(){}
    onMoveComplete(){}

    init(){
        for(let x=0;x<this.len;x++){
            this.arr[x]=[]
            for(let y=0;y<this.len;y++){
                this.arr[x][y]=0
            }
        }
        //console.log(this.arr);
    }
    generate(){
        let empty=[]
        for(let x=0;x<this.len;x++){
            for (let y = 0; y < this.len; y++) {
                if (this.arr[x][y]==0) {
                    empty.push({x:x,y:y})
                }
                
            }
        }
        let rnd=Math.floor(Math.random()*empty.length)

        let one=empty[rnd]
        this.arr[one.x][one.y]=Math.random()<0.5 ? 2:4

        this.onGenerate({
            x:one.x,
            y:one.y,
            num:this.arr[one.x][one.y]
        })

    }

    moveLeft(){
        let isMoved = false;
        // console.log(this.arr);

        for (let x = 0; x < this.len; x++) {
            for (let y = 0; y < this.len; y++) {
                
                for (let next = y+1; next < this.len; next++) {
                    if (this.arr[x][next]==0) {
                        continue
                    }
                    else{
                        if (this.arr[x][y]==0) {
                            //交换
                            this.arr[x][y]=this.arr[x][next]
                            // 在onMove()方法体中，调用view的move()方法，用于每当board类中保存的单元格移动时，控制页面中的单元格移动
                            this.onMove({
                                from:{x:x,y:next,num:this.arr[x][next]},
                                to:{x:x,y:y,num:this.arr[x][y]}
                            })
                            isMoved = true;
                            this.arr[x][next]=0
                            y--
                        }
                        else if (this.arr[x][y]==this.arr[x][next]) {
                            //合并
                            this.arr[x][y]+=this .arr[x][next]
                            this.onMove({
                                from:{x:x,y:next,num:this.arr[x][next]},
                                to:{x:x,y:y,num:this.arr[x][y]}
                            })
                            isMoved = true;
                            this.arr[x][next]=0
                        }
                    }
                    break
                }

                
            }
            
        }
        this.onMoveComplete({moved:isMoved},this.arr)

    }
    
    moveRight(){
        let isMoved = false;
        // console.log(this.arr);

        for (let x = 0; x < this.len; x++) {
            for (let y = this.len-1; y >= 0; y--) {
                
                for (let next = y-1; next >= 0; next--) {
                    if (this.arr[x][next]==0) {
                        continue
                    }
                    else{
                        if (this.arr[x][y]==0) {
                            //交换
                            this.arr[x][y]=this.arr[x][next]
                            this.onMove({
                                from:{x:x,y:next,num:this.arr[x][next]},
                                to:{x:x,y:y,num:this.arr[x][y]}
                            })
                            isMoved = true;
                            this.arr[x][next]=0
                            
                            y++
                        }
                        else if (this.arr[x][y]==this.arr[x][next]) {
                            //合并
                            this.arr[x][y]+=this .arr[x][next]
                            this.onMove({
                                from:{x:x,y:next,num:this.arr[x][next]},
                                to:{x:x,y:y,num:this.arr[x][y]}
                            })
                            isMoved = true;
                            this.arr[x][next]=0
                        }
                    }
                    break
                }

                
            }
            
        }
        this.onMoveComplete({moved:isMoved},this.arr)
    }

   
    moveTop(){
        let isMoved = false;
        // console.log(this.arr);

        for (let y = 0; y < this.len; y++) {
            for (let x = 0; x < this.len; x++) {
                
                for (let next = x+1; next < this.len; next++) {
                    if (this.arr[next][y]==0) {
                        continue
                    }
                    else{
                        if (this.arr[x][y]==0) {
                            //交换
                            this.arr[x][y]=this.arr[next][y]
                            this.onMove({
                                from:{x:next,y:y,num:this.arr[next][y]},
                                to:{x:x,y:y,num:this.arr[x][y]}
                            })
                            isMoved = true;
                            this.arr[next][y]=0
                            
                            x--
                        }
                        else if (this.arr[x][y]==this.arr[next][y]) {
                            //合并
                            this.arr[x][y]+=this .arr[next][y]
                            this.onMove({
                                from:{x:next,y:y,num:this.arr[next][y]},
                                to:{x:x,y:y,num:this.arr[x][y]}
                            })
                            isMoved = true;
                            this.arr[next][y]=0
                        }
                    }
                    break
                }

                
            }
            
        }
        this.onMoveComplete({moved:isMoved},this.arr)
    }

    moveBottom(){
        let isMoved = false;
        // console.log(this.arr);

        for (let y = 0; y < this.len; y++) {
            for (let x = this.len-1; x >= 0; x--) {
                
                for (let next = x-1; next >= 0; next--) {
                    if (this.arr[next][y]==0) {
                        continue
                    }
                    else{
                        if(this.arr[x][y]==0) {
                            //交换
                            this.arr[x][y]=this.arr[next][y]
                            this.onMove({
                                from:{x:next,y:y,num:this.arr[next][y]},
                                to:{x:x,y:y,num:this.arr[x][y]}
                            })
                            isMoved = true;
                            this.arr[next][y]=0
                            
                            x++
                        }
                        else if (this.arr[x][y]==this.arr[next][y]) {
                            //合并
                            this.arr[x][y]+=this .arr[next][y]
                            this.onMove({
                                from:{x:next,y:y,num:this.arr[next][y]},
                                to:{x:x,y:y,num:this.arr[x][y]}
                            })
                            isMoved = true;
                            this.arr[next][y]=0
                        }
                    }
                    break
                }

                
            }
            
        }
        this.onMoveComplete({moved:isMoved},this.arr)
    }

    canMove(){
        for(let x=0;x<this.len;x++){
            for(let y=0;y<this.len;y++){
                if(this.arr[x][y]==0){
                    return true
                }
                let cur=this.arr[x][y]
                let right=this.arr[x][y+1]
                let down=this.arr[x + 1] ? this.arr[x + 1][y] : null
                if(cur==right||cur==down){
                    return true
                }
            }
        }
        return false
      }

}